package net.siufung.core.utils;

import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * 拼音工具类
 * @author 陈建峰
 * @since 2022/2/9 11:10 下午
 */
@Slf4j
public class PinyinUtil {

    /**
     *  汉字正则表达式
     */
    private static final Pattern REG_CHINESE = Pattern.compile("[\u4e00-\u9fa5]");
    /**
     * 数字正则表达式
     */
    private static final Pattern REG_DIGIT = Pattern.compile("[0-9]");
    /**
     * 字母正则表达式
     */
    private static final Pattern REG_WORD = Pattern.compile("[a-zA-Z]");

    /**
     * 将文字转为汉语拼音
     * @param chineseLanguage 要转成拼音的中文
     * @return 汉语拼音
     */
    public String toHanyuPinyin(String chineseLanguage) {
        char[] clChars = chineseLanguage.trim().toCharArray();
        StringBuilder hanyupinyin = new StringBuilder();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        // 输出拼音全部小写
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 不带声调
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
        try {
            for (char clChar : clChars) {
                // 如果字符是中文,则将中文转为汉语拼音
                if (String.valueOf(clChar).matches("[\u4e00-\u9fa5]+")) {
                    hanyupinyin.append(PinyinHelper.toHanyuPinyinStringArray(clChar, defaultFormat)[0]);
                } else {
                    // 如果字符不是中文,则不转换
                    hanyupinyin.append(clChar);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            log.info("字符不能转成汉语拼音");
        }
        return hanyupinyin.toString();
    }

    /**
     * 大写拼音
     * @param chineseLanguage 要转成大写拼音的英文
     * @return 大写拼音的英文
     */
    public static String getFirstLettersUp(String chineseLanguage) {
        return getFirstLetters(chineseLanguage, HanyuPinyinCaseType.UPPERCASE);
    }

    /**
     * 小写拼音
     * @param chineseLanguage 要转成拼音的中文
     * @return 小写拼音
     */
    public static String getFirstLettersLo(String chineseLanguage) {
        return getFirstLetters(chineseLanguage, HanyuPinyinCaseType.LOWERCASE);
    }

    /**
     * 转化工具方法
     * @param chineseLanguage 要转成拼音的中文
     * @param hanyuPinyinCaseType 拼音类型
     * @return 拼音
     */
    private static String getFirstLetters(String chineseLanguage, HanyuPinyinCaseType hanyuPinyinCaseType) {
        char[] clChars = chineseLanguage.trim().toCharArray();
        StringBuilder hanyupinyin = new StringBuilder();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        // 输出拼音全部大写
        defaultFormat.setCaseType(hanyuPinyinCaseType);
        // 不带声调
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        try {
            for (char clChar : clChars) {
                String str = String.valueOf(clChar);
                // 如果字符是中文,则将中文转为汉语拼音,并取第一个字母
                if (str.matches("[\u4e00-\u9fa5]+")) {
                    hanyupinyin.append(PinyinHelper.toHanyuPinyinStringArray(clChar, defaultFormat)[0].charAt(0));
                    // 如果字符是数字,取数字
                } else if (str.matches("[0-9]+")) {
                    hanyupinyin.append(clChar);
                    // 如果字符是字母,取字母
                } else if (str.matches("[a-zA-Z]+")) {
                    hanyupinyin.append(clChar);
                } else {
                    // 否则不转换
                    //如果是标点符号的话，带着
                    hanyupinyin.append(clChar);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            log.info("字符不能转成汉语拼音");
        }
        return hanyupinyin.toString();
    }

    /**
     * 获得拼音字符串
     *
     * @param chineseLanguage 要转成拼音的中文
     * @return 拼音字符串
     */
    public static String getPinyinString(String chineseLanguage) {
        char[] clChars = chineseLanguage.trim().toCharArray();
        StringBuilder hanyupinyin = new StringBuilder();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        // 输出拼音全部大写
        defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 不带声调
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        try {
            for (char clChar : clChars) {
                String str = String.valueOf(clChar);
                // 如果字符是中文,则将中文转为汉语拼音,并取第一个字母
                if (str.matches("[\u4e00-\u9fa5]+")) {
                    hanyupinyin.append(PinyinHelper.toHanyuPinyinStringArray(
                            clChar, defaultFormat)[0]);
                    // 如果字符是数字,取数字
                } else if (str.matches("[0-9]+")) {
                    hanyupinyin.append(clChar);
                    // 如果字符是字母,取字母
                } else if (str.matches("[a-zA-Z]+")) {
                    hanyupinyin.append(clChar);
                }
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            log.info("字符不能转成汉语拼音");
        }
        return hanyupinyin.toString();
    }

    /**
     * 汉字转拼音
     *
     * @param chinese      需要转换的文字
     * @param firstLetters 是否取首字母
     * @param upperCase    是否转换为大写
     * @return 拼音
     */
    public static String[] getAllPinYin(String chinese, boolean firstLetters, boolean upperCase) {
        char[] chnChars = chinese.trim().toCharArray();
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        if (upperCase) {
            // 输出拼音全部大写
            format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        } else {
            // 输出拼音全部大写
            format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        }
        // 不带声调
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        String[] arr = new String[]{};
        try {
            for (char chnChar : chnChars) {
                String str = String.valueOf(chnChar);
                String[] pinyinArr;
                pinyinArr = PinyinHelper.toHanyuPinyinStringArray(chnChar, format);
                if (REG_CHINESE.matcher(str).matches()) {
                    if (firstLetters) {
                        pinyinArr = Arrays.stream(pinyinArr).map(p -> p.substring(0, 1)).toArray(String[]::new);
                    } else {
                        pinyinArr = Arrays.stream(pinyinArr).toArray(String[]::new);
                    }
                    arr = DescartesUtil.descartes(arr, Arrays.stream(pinyinArr).distinct().toArray(String[]::new));
                } else if (REG_DIGIT.matcher(str).matches()) {
                    arr = DescartesUtil.descartes(arr, new String[]{str});
                } else if (REG_WORD.matcher(str).matches()) {
                    arr = DescartesUtil.descartes(arr, new String[]{str});
                } else {
                    arr = DescartesUtil.descartes(arr, new String[]{str});
                }
            }
            arr = Arrays.stream(arr).distinct().toArray(String[]::new);
            return arr;
        } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
            badHanyuPinyinOutputFormatCombination.printStackTrace();
        }
        return new String[]{};
    }



    /**
     * 取第一个汉字的第一个字符
     * @param chineseLanguage 需要转换的文字
     * @return 第一个字符
     */
    public static String getFirstLetter(String chineseLanguage) {
        char[] clChars = chineseLanguage.trim().toCharArray();
        String hanyupinyin = "";
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        // 输出拼音全部大写
        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        // 不带声调
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        try {
            String str = String.valueOf(clChars[0]);
            // 如果字符是中文,则将中文转为汉语拼音,并取第一个字母
            if (str.matches("[\u4e00-\u9fa5]+")) {
                hanyupinyin = PinyinHelper.toHanyuPinyinStringArray(
                        clChars[0], defaultFormat)[0].substring(0, 1);
                // 如果字符是数字,取数字
            } else if (str.matches("[0-9]+")) {
                hanyupinyin += clChars[0];
                // 如果字符是字母,取字母
            } else if (str.matches("[a-zA-Z]+")) {
                hanyupinyin += clChars[0];
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            log.info("字符不能转成汉语拼音");
        }
        return hanyupinyin;
    }

}
